package model

import (
	"devOpsApi/common/util"
	"devOpsApi/model"
	"errors"
	"fmt"
	"reflect"
	"strings"
)

type Node struct {
	cli         *util.DockerCli
	containerID string
	pipeline    model.Pipeline
	Methods     map[string]bool
}

type QueryLine func(line string)

//动态调用
func DynamicInvoke(object interface{}, methodName string, args ...interface{}) []reflect.Value {
	inputs := make([]reflect.Value, len(args)) //参数slice
	for i, _ := range args {
		inputs[i] = reflect.ValueOf(args[i])
	}
	//动态调用方法
	r := reflect.ValueOf(object).MethodByName(methodName).Call(inputs)
	return r
	//动态访问属性
	//reflect.ValueOf(object).Elem().FieldByName("Name")
}

func NewNode(cli *util.DockerCli, containerID string, pipeline model.Pipeline) *Node {
	methods := make(map[string]bool)
	methods["Common"] = true
	methods["MvnTest"] = true
	return &Node{
		cli:         cli,
		containerID: containerID,
		pipeline:    pipeline,
		Methods:     methods,
	}
}

/*
	通用node构建方法
	参数
    a[0] setting 配置数据
    a[1] 回调函数

	返回数据
	string 运行日志字符
	error 结果
*/
func (m *Node) Common(a ...interface{}) (string, error) {
	if len(a) < 2 {
		return "", errors.New("通用方法参数丢失")
	}
	svValue := a[0].(map[string]interface{})
	QueryLine := a[1].(func(string))
	cmd := `#!/bin/bash
set -e
` + svValue["value"].(string)

	shellPath := "/tmp/pipeline.sh"
	err := m.cli.CopyToDockerByStr(CheckShellSuccess(cmd), shellPath, m.containerID)
	if err != nil {
		return "", err
	}

	line, err := m.cli.Exec(m.containerID, "/bin/bash "+shellPath, func(line string) {
		QueryLine(line)
	})
	if err != nil {
		return "", err
	}
	return line, nil
}

/*
	通用node构建方法
	参数
    a[0] setting 配置数据
    a[1] 回调函数

	返回数据
	string 运行日志字符
	error 结果
*/
func (m *Node) MvnTest(a ...interface{}) (string, error) {
	fmt.Println("MvnTest")
	return "", nil
}

//shell错误检测代码替换
func CheckShellSuccess(shell string) string {
	newShell := strings.ReplaceAll(shell, "#check#", `if [ $? -ne 0 ];then echo qmangoliaExitCode：${$?}; fi`)
	return newShell
}

//检查配置是否存在，不存在则返回error
func MapKeysExists(keys []string, setting map[string]string) error {
	for _, v := range keys {
		if _, ok := setting[v]; !ok {
			return errors.New("Setting [ " + v + " ] not find")
		}
	}
	return nil
}
